package socket.util;


import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.LinkedList;

/**
 * Created by cjx on 2019/8/7
 * 说明：和十六进制相关的一些转换工具
 */
public class ByteUtil {
    private static final String CHAR_LIST = "0123456789abcdef";

    /**
     * 十六进制的字符串转成byte数组
     *
     * @param hex 十六进制的字符串
     * @return 转换后的byte数组
     */
    public static byte[] hexStringToBytes(String hex) {
        if (hex == null) {
            return null;
        }
        hex = hex.toLowerCase();
        int length = hex.length() / 2;
        byte[] bytes = new byte[length];
        char[] chars = hex.toCharArray();
        for (int i = 0; i < length; i++) {
            int position = i * 2;
            bytes[i] = (byte) (charToByte(chars[position]) << 4 | charToByte(chars[position + 1]));
        }
        return bytes;
    }

    /**
     * 将一个字符转成字节
     *
     * @param c 字符
     * @return 转换后的字节
     */
    public static byte charToByte(char c) {
        return (byte) CHAR_LIST.indexOf(c);
    }

    /**
     * 将byte转成十六进制的字符串
     *
     * @param b 可以表示十六进制的字节
     * @return 十六进制的字符串
     */
    public static String byteToHexString(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            hex = "0" + hex;
        }
        return hex;
    }

    public static String byteToString(byte b) {
        String hex = String.valueOf((int) b);
        if (hex.length() == 1) {
            hex = "0" + hex;
        }
        return hex;
    }


    /**
     * 将byte转成十进制数
     *
     * @param b 可以表示十六进制的字节
     * @return 十进制的整数
     */
    public static int hexByteToInt(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            hex = "0" + hex;
        }
        return Integer.parseInt(hex, 16);
    }

    /**
     * 十六进制的字符串转成int类型
     *
     * @param hex 十六进制字符串
     * @return 对应的十进制数
     */
    public static int hexStringToInt(String hex) {
        return Integer.parseInt(hex, 16);
    }

    public static int stringToInt(String str) {
        return Integer.parseInt(str);
    }

    /**
     * 将十进制数转成十六进制的字符串
     *
     * @return 十六进制的字符串
     */
    public static String intToHexString(int src) {
        return Integer.toHexString(src);
    }

    public static byte intToByte(int src) {
        return (byte) src;
    }

    /**
     * 将一个word转成int
     *
     * @param low    小端
     * @param height 大端
     * @return 对应的int值
     */
    public static int wordToInt(byte low, byte height) {
        return ByteUtil.byteToInt(height) * 256 + ByteUtil.byteToInt(low);
    }

    /**
     * 获取链表头部两个字节转换成一个整形，并从链表头部移除
     *
     * @param bytes byte链表
     * @return 转换出来的数字
     */
    public static int getTopWordToInt(LinkedList<Byte> bytes) {
        return wordToInt(bytes.pop(), bytes.pop());
    }

    public static int byteToInt(byte b) {
        String hex = Integer.toHexString(b & 0xFF);
        return Integer.parseInt(hex, 16);
    }

    /**
     * 将输入流全部读到一个byte链表中
     *
     * @param inputStream socket输入流
     * @return 读出来后的byte链表
     */
    public static LinkedList<Byte> readAllByte(DataInputStream inputStream, int defaultByteSize) throws IOException {
        LinkedList<Byte> bytes = new LinkedList<>();
        byte[] flow = new byte[defaultByteSize];
        int length = inputStream.read(flow);

        for (int i = 0; i < length; i++) {
            bytes.addLast(flow[i]);
        }
        if (length == defaultByteSize) {
            int available = inputStream.available();
            if (available > 1) {
                byte[] bs = new byte[available];
                inputStream.readFully(bs);

                for (byte b : bs) {
                    bytes.addLast(b);
                }
            }

        }

        return bytes;
    }

    /**
     * 检测第几位是否为1，用于解析判断设备上报的报警码1，
     *
     * @param src
     * @param poi
     * @return
     */
    public static boolean checkBit(int src, int poi) {
        return (src >> poi & 0x01) == 1;
    }

    /**
     * 获取一串数字转化的字节流
     */
    public static byte[] generateData(int... code) {
        int length = code.length;
        byte[] data = new byte[length * 2];
        for (int i = 0; i < length; i++) {
            data[i * 2] = (byte) (code[i] % 256);
            data[i * 2 + 1] = (byte) (code[i] / 256);
        }
        return data;
    }

    public static int getInt(byte[] b) {
        byte[] a = new byte[4];
        int i = a.length - 1, j = b.length - 1;
        for (; i >= 0; i--, j--) {//从b的尾部(即int值的低位)开始copy数据
            if (j >= 0)
                a[i] = b[j];
            else
                a[i] = 0;//如果b.length不足4,则将高位补0
        }
        int v0 = (a[0] & 0xff) << 24;//&0xff将byte值无差异转成int,避免Java自动类型提升后,会保留高位的符号位
        int v1 = (a[1] & 0xff) << 16;
        int v2 = (a[2] & 0xff) << 8;
        int v3 = (a[3] & 0xff);
        return v0 + v1 + v2 + v3;
    }

    public static void putFloat(byte[] bb, float x) {
        int l = Float.floatToIntBits(x);
        bb[3] = (byte) (l & 0xff);
        bb[2] = (byte) ((l & 0xff00) >> 8);
        bb[1] = (byte) ((l & 0xff0000) >> 16);
        bb[0] = (byte) ((l & 0xff000000) >> 24);
    }

    public static float getSpecailFloat(int high_8, int low_8) {
        int data = (high_8 & 0xffff) << 16;
        data |= (low_8 & 0xffff);
        return Float.intBitsToFloat(data);
    }

    public static int insertByteInInt(int data, int index) {
        data = data | (0x1 << index);
        return data;
    }

    /**
     * 十六进制的字符串转成int数组
     *
     * @param hex 十六进制的字符串
     * @return 转换后的byte数组
     */
    public static int[] hexStringToInts(String hex) {
        if (hex == null) {
            return null;
        }
        hex = hex.toLowerCase();
        int length = hex.length() / 2;
        int[] datas = new int[length];
        char[] chars = hex.toCharArray();
        for (int i = 0; i < length; i++) {
            int position = i * 2;
            byte b = (byte) (charToByte(chars[position]) << 4 | charToByte(chars[position + 1]));
            datas[i] = hexByteToInt(b);
        }
        return datas;
    }

    /**
     * 十六进制的字符串转成int数组
     *
     * @param hex 十六进制的字符串
     * @return 转换后的byte数组
     */
    public static int[] hex4StringToInts(String hex) {
        if (hex == null) {
            return null;
        }
        hex = hex.toLowerCase();
        int length = hex.length() / 2;
        int[] datas = new int[length];
        char[] chars = hex.toCharArray();
        for (int i = 0; i < length; i++) {
            int position = i * 2;
            byte b = (byte) (charToByte(chars[position]) << 4 | charToByte(chars[position + 1]));
            datas[i] = hexByteToInt(b);
        }
        return datas;
    }

    public static byte[] toByteArray(long value) {
        return ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(value).array();
    }

    public static long byteArrayToLong(byte[] bytes) {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.put(bytes, 0, bytes.length);
        buffer.flip();
        return buffer.getLong();
    }

    public static void main(String[] args) {
        long time = System.currentTimeMillis();

        byte[] g = toByteArray(time);
        long time2 = byteArrayToLong(g);
        System.out.println("t "+time+" "+g.length+" time2 "+time2);
    }
}
